// noinspection JSUnusedLocalSymbols
const config = require('./config/config.js'); // 保证第一个加载config.js
const logger = require('./middlewares/logger');
const Koa = require('koa');
const koaBody = require('koa-body');
const jwt = require('koa-jwt');

logger.info('加载配置 config_id:', global.gConfig.config_id);
logger.info('开始启动...');
const app = new Koa();

//非生产环境运行时打印所有请求信息
if ('production' !== global.gConfig.config_id) {
    app.use(async (ctx, next) => {
        const start = Date.now();
        logger.debug('请求信息', JSON.stringify(ctx.request));
        await next();
        const ms = Date.now() - start;
        logger.debug(`响应时间${ms}`, '响应信息', JSON.stringify(ctx.response));
    });
    logger.debug('加载开发环境中间件====>打印请求体与返回值');
}

//返回值格式化
app.use(async (ctx, next) => {
    await next();
    if (ctx.status >= 200 && ctx.status < 400) {
        ctx.body = { success: true, code: ctx.status, data: ctx.body };
    } else {
        ctx.body = {
            success: false,
            code: ctx.status,
            // 当有未捕获的异常出现时, 错误信息在body里; 保证取错误信息的顺序是 body -> message
            msg: ctx.body || ctx.message
        };
    }
});
logger.info('加载中间件====>返回值格式化');

//错误捕获中间件
app.use(async (ctx, next) => {
    try {
        await next();
    } catch (err) {
        ctx.status = err.status || 500;
        // 当捕获到异常时, 不要放到ctx.message里, 要放到ctx.body里. 因为如果错误信息里有中文时, koa会直接出错
        ctx.body = err.message;
        ctx.app.emit('error', err, ctx);
    }
});
logger.info('加载中间件====>异常捕获中间件');

//加载登陆验证器
app.use(
    jwt({ secret: global.gConfig.port, cookie: 'jwt' }).unless({
        path: [/\/api/]
    })
);
logger.info('加载中间件====>登陆验证');

//post请求体格式化
app.use(
    koaBody({
        multipart: true,
        formidable: {
            maxFileSize: 100 * 1024 * 1024
        }
    })
);
logger.info('加载中间件====>请求体格式化');

//添加所有router
const router = require('./middlewares/router');
app.use(router.routes()).use(router.allowedMethods());
logger.info('加载中间件====>所有router');

app.on('error', (err, ctx) => {
    logger.error(err);
});

app.listen(global.gConfig.port);
logger.info('项目启动完成');
